package systemInformation;

import java.util.ArrayList;
import java.util.List;
import java.util.Vector;

import org.snmp4j.PDU;
import org.snmp4j.agent.mo.snmp.DisplayString;
import org.snmp4j.smi.Integer32;
import org.snmp4j.smi.VariableBinding;

import features.SNMPException;
import features.SNMPSession;
import features.SNMPValue;

public class ProcessInfo {
	private final static String INDEX_OID = 	".1.3.6.1.2.1.25.4.2.1.1";
	
	private final static String NAME_OID = 		".1.3.6.1.2.1.25.4.2.1.2";
	
	private final static String STATUS_OID = 	".1.3.6.1.2.1.25.4.2.1.7";
	
	private final static String TYPE_OID = 		".1.3.6.1.2.1.25.4.2.1.6";
	
	private final static String CPU_TIME_OID = 	".1.3.6.1.2.1.25.5.1.1.1";
	
	private final static String MEMORY_OID = 	".1.3.6.1.2.1.25.5.1.1.2";
	
	private int index;

	private String name;

	private String type;

	private String status;

	private long cpuTime;

	private long memory; //in Byte
	
	@SuppressWarnings("unchecked")
	public static ProcessInfo fromPDU(PDU pdu) {
		ProcessInfo info = new ProcessInfo();
		Vector<VariableBinding> variableBindings = pdu.getVariableBindings();
		
		for (VariableBinding variableBinding : variableBindings) {
			if(variableBinding.getOid().compareTo(INDEX_OID) == 0) {
				info.setIndex(((Integer32) variableBinding.getVariable()).getValue());
			} else if(variableBinding.getOid().compareTo(NAME_OID) == 0) {
				info.setName(((DisplayString) variableBinding.getVariable()).toString());
			} else if(variableBinding.getOid().compareTo(STATUS_OID) == 0) {
				info.setStatus(ProcessStatus.fromVariable((Integer32) variableBinding.getVariable()).toString());
			} else if(variableBinding.getOid().compareTo(TYPE_OID) == 0) {
				info.setType(ProcessType.fromVariable((Integer32) variableBinding.getVariable()).toString());
			} else if(variableBinding.getOid().compareTo(CPU_TIME_OID) == 0) {
				info.setCpuTime(((Integer32) variableBinding.getVariable()).getValue());
			} else if(variableBinding.getOid().compareTo(MEMORY_OID) == 0) {
				info.setMemory(((Integer32) variableBinding.getVariable()).getValue());
			}
		}
		
		return info;
	}

	public static List<ProcessInfo> fromSession(SNMPSession session) throws SNMPException {
		List<ProcessInfo> processes = new ArrayList<ProcessInfo>();
		List<SNMPValue> lstIndex = session.getColumn(INDEX_OID);
		List<SNMPValue> lstName = session.getColumn(NAME_OID);
		List<SNMPValue> lstStatus= session.getColumn(STATUS_OID);
		List<SNMPValue> lstType = session.getColumn(TYPE_OID);
		List<SNMPValue> lstCpuTime = session.getColumn(CPU_TIME_OID);
		List<SNMPValue> lstMemory = session.getColumn(MEMORY_OID);
		
		for (int i = 0; i < lstName.size(); i++) {
			ProcessInfo info = new ProcessInfo();
			
			info.setIndex(lstIndex.get(i).toInt());
			info.setName(lstName.get(i).toString());
			info.setStatus(ProcessStatus.fromInt(lstStatus.get(i).toInt()).toString());
			info.setType(ProcessType.fromInt(lstType.get(i).toInt()).toString());
			info.setCpuTime(lstCpuTime.get(i).toLong());
			info.setMemory(lstMemory.get(i).toLong());
			
			processes.add(info);
		}
		
		return processes;
	}
	
	@Override
	public String toString() {
		return "ProcessInfo [" + index + ", " + name + ", " + status + ", " + type + ", " + cpuTime + ", " + memory + "]";
	}
	
	public long getCpuTime() {
		return this.cpuTime;
	}

	public void setCpuTime(long cpuTime) {
		this.cpuTime = cpuTime;
	}

	public int getIndex() {
		return this.index;
	}

	public void setIndex(int index) {
		this.index = index;
	}

	public long getMemory() {
		return this.memory;
	}

	public void setMemory(long memory) {
		this.memory = memory;
	}

	public String getName() {
		return this.name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getStatus() {
		return this.status;
	}

	public void setStatus(String status) {
		this.status = status;
	}

	public String getType() {
		return this.type;
	}

	public void setType(String type) {
		this.type = type;
	}

	@Override
	public int hashCode() {
		final int PRIME = 31;
		int result = 1;
		result = PRIME * result + (int) (this.cpuTime ^ (this.cpuTime >>> 32));
		result = PRIME * result + this.index;
		result = PRIME * result + (int) (this.memory ^ (this.memory >>> 32));
		result = PRIME * result + ((this.name == null) ? 0 : this.name.hashCode());
		result = PRIME * result + ((this.status == null) ? 0 : this.status.hashCode());
		result = PRIME * result + ((this.type == null) ? 0 : this.type.hashCode());
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		final ProcessInfo other = (ProcessInfo) obj;
		if (this.cpuTime != other.cpuTime)
			return false;
		if (this.index != other.index)
			return false;
		if (this.memory != other.memory)
			return false;
		if (this.name == null) {
			if (other.name != null)
				return false;
		} else if (!this.name.equals(other.name))
			return false;
		if (this.status == null) {
			if (other.status != null)
				return false;
		} else if (!this.status.equals(other.status))
			return false;
		if (this.type == null) {
			if (other.type != null)
				return false;
		} else if (!this.type.equals(other.type))
			return false;
		return true;
	}
}
